home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / CH_5.2 / structfeat / structfeat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  8.4 KB  |  252 lines

  1. /*
  2.  * structfeat.c
  3.  *
  4.  * Practical Algorithms for Image Analysis
  5.  *
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /* STRUCTFEAT:  program decodes PCC and writes out line structure features
  10.  *                usage: structfeat in.pcc out.pcc
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "pcc2.h"               /* header file for PCC programs */
  17. extern void print_sos_lic ();
  18.  
  19. unsigned char *fcCode;          /* code storage */
  20. long nByteCode;                 /* no. bytes in code storage */
  21.  
  22. long tlc3rid (struct attributes *, long, struct structures *,
  23.               long *, long, long, long, long);
  24. long usage (short);
  25. long input (int, char **, short *);
  26.  
  27. main (argc, argv)
  28.      int argc;
  29.      char *argv[];
  30.  
  31. {
  32.   long width, height;           /* image size */
  33.   short sumFlag;                /* flag=1 to print only summary; 0 otherwise */
  34.   struct attributes *attr;      /* level 1 attributes */
  35.   long nAttr;                   /* no. of line structures in attr. array */
  36.   struct structures *structs;   /* level 3 line structures */
  37.   long nStructs;                /* no. of connected structures in image */
  38.   long sumNLines;               /* sum of no. of lines in all struct.s */
  39.   long sumNEnds;                /* sum of no. of endlines in all struct.s */
  40.   long sumLength;               /* sum of total line lengths for all structs */
  41.   long sumMaxLength;            /* sum of max. line lengths in all structs */
  42.   double sumX, sumY;            /* sum of structure x,y centroids */
  43.   long sumBoxX, sumBoxY;        /* sum of x,y bounding box lengths */
  44.   long sumArea;                 /* sum of bounding box areas */
  45.   int i;
  46.  
  47.   if (input (argc, argv, &sumFlag) < 0)
  48.     return (-1);
  49.  
  50. /* open input PCC file */
  51.   if (pccread (argv[1], &fcCode, &nByteCode, &width, &height) == -1)
  52.     exit (1);
  53.   printf ("image size: %dx%d, PCC length = %d\n",
  54.           width, height, nByteCode);
  55.  
  56. /* construct tables of PCC decodes */
  57.   pccdecodes ();
  58.  
  59. /* construct TLC level 1 array of attributes */
  60.   tlc1attr (&attr, &nAttr);
  61.   printf ("%d level 1 line features\n", nAttr);
  62.  
  63. /* find level 3 connected structures */
  64.   tlc3structs (attr, nAttr, &structs, &nStructs);
  65.  
  66. /* determine level 3 features */
  67.   tlc3feats (attr, nAttr, structs, nStructs);
  68.  
  69. /* summary information */
  70.   sumNLines = sumNEnds = sumLength = sumMaxLength = 0;
  71.   sumX = sumY = 0.0;
  72.   sumBoxX = sumBoxY = sumArea = 0;
  73.   for (i = 0; i < nStructs; i++) {
  74.     sumNLines += structs[i].nLines;
  75.     sumNEnds += structs[i].nEnds;
  76.     sumLength += structs[i].length;
  77.     sumMaxLength += structs[i].maxLength;
  78.     sumX += structs[i].centroidX;
  79.     sumY += structs[i].centroidY;
  80.     sumBoxX += (structs[i].box.max.x - structs[i].box.min.x);
  81.     sumBoxY += (structs[i].box.max.y - structs[i].box.min.y);
  82.     sumArea += (structs[i].box.max.x - structs[i].box.min.x)
  83.       * (structs[i].box.max.y - structs[i].box.min.y);
  84.   }
  85.   printf ("Structure Feature Summary:\n");
  86.   printf ("\tnumber of line structures = %d\n", nStructs);
  87.   printf ("\taverage number of lines per structure = %5.1f\n",
  88.           (double) sumNLines / (double) nStructs);
  89.   printf ("\taverage number of endlines per structure = %5.1f\n",
  90.           (double) sumNEnds / (double) nStructs);
  91.   printf ("\taverage total line length per structure %5.1f\n",
  92.           (double) sumLength / ((double) nStructs * 10.0));
  93.   printf ("\taverage maximum line length per structure = %5.1f\n",
  94.           (double) sumMaxLength / ((double) nStructs * 10.0));
  95.   printf ("\taverage bounding box size = %5.1f x %5.1f, area = %5.1f [pix]\n",
  96.           (double) sumBoxX / (double) nStructs,
  97.           (double) sumBoxY / (double) nStructs,
  98.           (double) sumArea / (double) nStructs);
  99.   printf ("\taverage of structure centroids = (%5.1f,%5.1f) [pixels]\n",
  100.           sumX / (double) nStructs,
  101.           sumY / (double) nStructs);
  102.  
  103. /* print features for each line structure */
  104.  
  105.   if (sumFlag)
  106.     return (-1);
  107.   printf ("\nLine Structure Features:\n");
  108.   for (i = 0; i < nStructs; i++) {
  109.     printf ("\n%d: ", i);
  110.     printf ("\tno. lines = %d, no. endlines = %d\n",
  111.             structs[i].nLines, structs[i].nEnds);
  112.     printf ("\ttotal line length = %5.1f, max. length of a segment = %5.1f\n",
  113.             (double) structs[i].length / 10.0,
  114.             (double) structs[i].maxLength / 10.0);
  115.     printf ("\tbounding box: (%d,%d),(%d,%d), area = %d\n",
  116.             structs[i].box.min.x, structs[i].box.min.y,
  117.             structs[i].box.max.x, structs[i].box.max.y,
  118.             (structs[i].box.max.x - structs[i].box.min.x)
  119.             * (structs[i].box.max.y - structs[i].box.min.y));
  120.     printf ("\tcentroid: (%5.1f,%5.1f)\n",
  121.             structs[i].centroidX, structs[i].centroidY);
  122.   }
  123.  
  124.   return (0);
  125. }
  126.  
  127.  
  128.  
  129. /* TLC3RID:   function removes any level 3 structures above or below threshold
  130.  *              usage: tlc3rid (attr, nAttr, structs, &nStructs,
  131.  *                                  lowLength, highLength, lowArea, highArea)
  132.  */
  133.  
  134. long
  135. tlc3rid (attr, nAttr, structs, nStructs, lowLength, highLength,
  136.          lowArea, highArea)
  137.      struct attributes *attr;   /* level 1 attributes */
  138.      long nAttr;                /* no. level 1 attributes */
  139.      struct structures *structs;  /* level 3 attributes */
  140.      long *nStructs;            /* no. level 3 attributes */
  141.      long lowLength, highLength,  /* length range to retain (*10) */
  142.        lowArea, highArea;       /* area range to retain */
  143. {
  144.   long strtCode, endCode,       /* bounds of code for structure */
  145.     iStopByte,                  /* position of STOPBYTE */
  146.     nStructsOut,                /* no. of structures after removal */
  147.     iStructs,                   /* level 3 increment */
  148.     iCode,                      /* input PCC incrementor */
  149.     iOut;                       /* output PCC incrementor */
  150.   struct structures strct;      /* level 3 structure */
  151.   long lx, ly,                  /* lengths of bounding box */
  152.     area;                       /* area of bounding box */
  153.  
  154. /* find position of STOPCODE (I'm inconsistent I think in putting 4 bytes
  155.  * trailing this or not, so we'll find it) */
  156.   for (iStopByte = nByteCode - 1; iStopByte > 0; --iStopByte)
  157.     if (fcCode[iStopByte] == STOPCODE)
  158.       break;
  159.  
  160. /* read code, and write code which is not deleted */
  161.   nStructsOut = 0;
  162.   for (iStructs = 0, iOut = 0; iStructs < *nStructs; iStructs++) {
  163.     strct = structs[iStructs];
  164.     strtCode = attr[strct.iAttr].iByteCode - 5;
  165.     endCode = (iStructs + 1 < *nStructs) ?
  166.       attr[structs[iStructs + 1].iAttr].iByteCode - 6 : iStopByte - 1;
  167.     lx = (strct.box.max.x - strct.box.min.x);
  168.     ly = (strct.box.max.y - strct.box.min.y);
  169.     if (lx == 0)
  170.       lx = 1;
  171.     if (ly == 0)
  172.       ly = 1;
  173.     area = lx * ly;
  174.     if (area < 0)
  175.       area *= -1;
  176.     if (strct.length >= lowLength && strct.length < highLength
  177.         && area >= lowArea && area < highArea) {
  178.       nStructsOut++;
  179.       for (iCode = strtCode; iCode <= endCode; iCode++)
  180.         fcCode[iOut++] = fcCode[iCode];
  181.     }
  182.   }
  183.  
  184.   for (iCode = iStopByte; iCode < nByteCode; iCode++)
  185.     fcCode[iOut++] = fcCode[iCode];
  186.   *nStructs = nStructsOut;
  187.   nByteCode = iOut;
  188.   return (0);
  189. }
  190.  
  191.  
  192.  
  193. /* USAGE:       function gives instructions on usage of program
  194.  *                    usage: usage (flag)
  195.  *              When flag is 1, the long message is given, 0 gives short.
  196.  */
  197.  
  198. long
  199. usage (flag)
  200.      short flag;                /* flag =1 for long message; =0 for short message */
  201. {
  202.  
  203. /* print short usage message or long */
  204.   printf ("USAGE: structfeat infile [-s] [-L]\n");
  205.   if (flag == 0)
  206.     return (-1);
  207.  
  208.   printf ("\nstructfeat lists line structures, that is, objects\n");
  209.   printf ("made up of one or many connected line segments.\n\n");
  210.   printf ("ARGUMENTS:\n");
  211.   printf ("    infile: input filename (PCC) \n\n");
  212.   printf ("OPTIONS:\n");
  213.   printf ("        -s: print summary only.\n");
  214.   printf ("        -L: print Software License for this module\n");
  215.  
  216.   return (-1);
  217. }
  218.  
  219.  
  220. /* INPUT:       function reads input parameters
  221.  *                    usage: input (argc, argv, &sumFlag)
  222.  */
  223.  
  224. #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
  225.  
  226. long
  227. input (argc, argv, sumFlag)
  228.      int argc;
  229.      char *argv[];
  230.      short *sumFlag;            /* flag =1, print only summary; 0 otherwise */
  231. {
  232.   long n;
  233.  
  234.   if (argc == 1)
  235.     USAGE_EXIT (1);
  236.  
  237.   *sumFlag = 0;
  238.  
  239.   for (n = 2; n < argc; n++) {
  240.     if (strcmp (argv[n], "-s") == 0)
  241.       *sumFlag = 1;
  242.     else if (strcmp (argv[n], "-L") == 0) {
  243.       print_sos_lic ();
  244.       exit (0);
  245.     }
  246.     else
  247.       USAGE_EXIT (0);
  248.   }
  249.  
  250.   return (0);
  251. }
  252.